﻿using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Quartz.Xml.JobSchedulingData20;
using Simple.Common.Authentication;
using Simple.Common.Authentication.Jwt;
using Simple.Common.EventBus;
using Simple.Common.Models;
using Simple.Services.Account.Models;
using Simple.Services.System.FileInfo;
using StackExchange.Redis;
using UAParser;

namespace Simple.Services;

public class AccountService
{
    private readonly SimpleDbContext _context;
    private readonly ISimpleService _simpleService;
    private readonly ICurrentUserService _currentUser;
    private readonly CacheService _cacheService;
    private readonly UserService _userService;
    private readonly FileInfoService _fileInfoService;
    private readonly OrganizationService _organizationService;
    private readonly IEventPublisher _publisher;
    private readonly IHttpContextAccessor _httpContextAccessor;
    public AccountService(SimpleDbContext context,
                          ISimpleService simpleService,
                          ICurrentUserService currentUser,
                          CacheService cacheService,
                          UserService userService,
                          RoleService roleService,
                          FileInfoService fileInfoService,
                          OrganizationService organizationService,
                          IEventPublisher eventPublisher,
                          IHttpContextAccessor httpContextAccessor)
    {
        _context = context;
        _simpleService = simpleService;
        _currentUser = currentUser;
        _userService = userService;
        _cacheService = cacheService;
        _fileInfoService = fileInfoService;
        _organizationService = organizationService;
        _publisher = eventPublisher;
        _httpContextAccessor = httpContextAccessor;
    }

    /// <summary>
    /// 获取 JwtToken
    /// </summary>
    /// <param name="login"></param>
    /// <returns></returns>
    public async Task<string> GetTokenAsync(LoginModel login)
    {
        var error = string.Empty;
        // var passwordHash = HashHelper.Md5(login.Password);

        var user = await _context.Set<SysUser>()
            .Include(u => u.UserRoles)
            .Where(u => u.UserName == login.Account)
            .Where(u => u.Password == login.Password)
            .FirstOrDefaultAsync();

        if (user == null)
        {
            error = "用户不存在或密码不匹配";
        }
        else
        {
            if (!user.IsEnabled)
            {
                error = "该账号已被停用";
            }
        }
        #region 登录日志
        PublishLoginLog(login.Account, 0, 0, error);
        #endregion

        if (!string.IsNullOrWhiteSpace(error))
        {
            throw AppResultException.Status403Forbidden(error);
        }

        // 用户信息
        List<Claim> claims = new List<Claim>()
        {
            new Claim(SimpleClaimTypes.UserId, user.Id.ToString()),
            new Claim(SimpleClaimTypes.Name, user.Name ?? ""),
            new Claim(SimpleClaimTypes.Email, user.Email?? ""),
            new Claim(SimpleClaimTypes.AdminType, user.AdminType.ToString()),
            new Claim(SimpleClaimTypes.OrganizationId, user.OrganizationId.ToString()),
            new Claim(SimpleClaimTypes.LoginSource, "0"),
            new Claim(SimpleClaimTypes.LoginType, LoginType.GardenSide.ToString()),
        };
        string[] roles = user.UserRoles.Select(ur => ur.RoleId.ToString()).ToArray();

        // 生成 token
        var jwtTokenModel = new JwtTokenModel(login.Account, claims, roles);
        string token = JwtHelper.Create(jwtTokenModel);

        return token;
    }

    /// <summary>
    /// 获取用户信息（适配小诺1.8 vue前端）
    /// </summary>
    /// <returns></returns>
    public async Task<UserInfoModel> GetUserInfoAsync()
    {
        if (_currentUser.UserId == null)
        {
            throw AppResultException.Status401Unauthorized();
        }

        var result = new UserInfoModel();

        // 关联 UserRole 查询用户
        var user = await _context.Set<SysUser>()
            .Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
            .Include(u => u.UserDataScopes)
            .Where(u => u.Id == _currentUser.UserId)
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw AppResultException.Status404NotFound("找不到用户信息");
        }

        // SysUser 映射为 UserInfoModel
        MapperHelper.Map(user, result);

        // 角色Id 列表
        var roleIds = user.UserRoles.Select(ur => ur.RoleId);

        // Roles 角色信息
        List<SysRole> roles = user.UserRoles.Where(ur => ur.Role != null).Select(ur => ur.Role!).ToList();
        result.Roles = MapperHelper.Map<List<UserInfoRoleModel>>(roles);

        // Apps 应用信息
        result.Apps = await GetUserApplicationsAsync(user);
        // 如果没有默认应用，设定第一个为默认应用
        if (result.Apps.Count > 0 && !(result.Apps.Any(a => a.Active)))
        {
            result.Apps[0].Active = true;
        }

        // Menus 菜单信息
        result.Menus = await GetUserMenusAsync(user);
        result.Avatar = await _fileInfoService.GetUserPortrait(_currentUser.UserId.Value);
        // Permissions 权限信息
        result.Permissions = await GetUserPermissionsAsync(user);
        result.DataScopes = await _organizationService.GetPrimaryOrganization();
        return result;
    }

    /// <summary>
    /// 当前用户是否为超级管理员
    /// </summary>
    /// <returns></returns>
    public bool IsSuperAdmin()
    {
        return _currentUser.IsSuperAdmin;
    }

    public bool IsAuthenticated()
    {
        return _currentUser.IsAuthenticated;
    }
    public bool IsApp()
    {
        return _currentUser.IsApp;
    }

    /// <summary>
    /// 获取当前用户应用列表
    /// </summary>
    /// <returns></returns>
    public async Task<List<UserInfoApplicationModel>> GetUserApplicationsAsync()
    {
        // 通过构建一个 SysUser 对象，来获取结果
        SysUser? user = BuildCurrentUser();
        if (user == null)
        {
            // 如果是在权限过滤器中抛出，将不会被处理为返回结果，因为 AuthorizationFilter 先于 ActionFilter
            //throw AppResultException.Status401Unauthorized("用户不存在");

            // 直接返回空结果，表示没有任何权限
            return new List<UserInfoApplicationModel>();
        }

        // 获取结果
        return await GetUserApplicationsAsync(user);
    }

    /// <summary>
    /// 获取用户应用列表
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<UserInfoApplicationModel>> GetUserApplicationsAsync(Guid userId)
    {
        // 关联 UserRole 查询用户
        var user = await _context.Set<SysUser>()
            .Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
            .Where(u => u.Id == userId)
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw AppResultException.Status404NotFound("用户不存在");
        }

        return await GetUserApplicationsAsync(user);
    }

    /// <summary>
    /// 获取用户应用列表
    /// </summary>
    /// <param name="user">包含角色信息的用户数据</param>
    /// <returns></returns>
    public async Task<List<UserInfoApplicationModel>> GetUserApplicationsAsync(SysUser user)
    {
        if (user.AdminType == AdminType.SuperAdmin)
        {
            // 超级管理员用户
            // 优先读缓存
            List<ApplicationCacheItem> applicationCacheItems = await _cacheService.GetUserApplicationsAsync(user.Id);
            if (applicationCacheItems.Count > 0)
            {
                // 去重并排序
                applicationCacheItems = applicationCacheItems.Distinct().OrderBy(a => a.Sort).ToList();

                // 返回结果
                return MapperHelper.Map<List<UserInfoApplicationModel>>(applicationCacheItems);
            }

            // 没有缓存，从数据库读取所有应用
            var applications = _context.Set<SysApplication>()
                .OrderBy(a => a.Sort)
                .Distinct()
                .ToList();

            // 缓存管理员用户应用信息
            applicationCacheItems = MapperHelper.Map<List<ApplicationCacheItem>>(applications);
            await _cacheService.SetUserApplicationAsync(user.Id, applicationCacheItems);

            // 返回结果集
            return MapperHelper.Map<List<UserInfoApplicationModel>>(applications);
        }
        else
        {
            // 其他用户
            // 获取用户角色列表
            var roleIds = user.UserRoles.Select(ur => ur.RoleId);

            // 返回角色应用列表
            return await GetRoleApplicationsAsync(roleIds.ToArray());
        }
    }

    /// <summary>
    /// 获取角色应用列表
    /// </summary>
    /// <param name="roleIds"></param>
    /// <returns></returns>
    public async Task<List<UserInfoApplicationModel>> GetRoleApplicationsAsync(params Guid[] roleIds)
    {

        // 优先读取缓存
        List<ApplicationCacheItem> applicationCacheItems = await _cacheService.GetRoleApplicationsAsync(roleIds);
        if (applicationCacheItems.Count > 0)
        {
            // 去重并排序
            applicationCacheItems = applicationCacheItems.Distinct().OrderBy(a => a.Sort).ToList();

            // 返回结果
            return MapperHelper.Map<List<UserInfoApplicationModel>>(applicationCacheItems);
        }

        // 没有缓存，读数据库
        // step1: 获取角色拥有的菜单
        var roles = await _context.Set<SysRole>()
            .Include(r => r.RoleMenus.Where(rm => rm.Menu!.IsEnabled)
                                     .Where(rm => rm.Menu!.Type != MenuType.Button)
            )
            .ThenInclude(rm => rm.Menu)
            .Where(r => roleIds.Contains(r.Id))
            .ToListAsync();

        // step2: 获取 ApplicationCode 列表
        List<string> applicationCodes = roles.SelectMany(r => r!.RoleMenus)
            .Where(rm => rm.Menu != null).Select(rm => rm.Menu!)
            .Where(m => m.Application != null).Select(m => m!.Application!).ToList();

        // step3: 获取 Application 列表
        var applications = _context.Set<SysApplication>()
            .Where(a => applicationCodes.Contains(a.Code))
            .OrderBy(a => a.Sort)
            .Distinct()
            .ToList();

        // step4: 缓存
        foreach (var role in roles)
        {
            List<string> roleApplicationCodes = role.RoleMenus
                .Where(rm => rm.Menu != null).Select(rm => rm.Menu!)
                .Where(m => m.Application != null).Select(m => m!.Application!).ToList();

            List<SysApplication> roleApplications = applications.Where(a => applicationCodes.Contains(a.Code)).ToList();

            if (roleApplications.Any())
            {
                // 添加缓存
                var roleApplicationCacheItems = MapperHelper.Map<List<ApplicationCacheItem>>(roleApplications);
                await _cacheService.SetRoleApplicationAsync(role.Id, roleApplicationCacheItems);
            }
        }

        return MapperHelper.Map<List<UserInfoApplicationModel>>(applications);
    }

    /// <summary>
    /// 获取当前用户菜单列表（AntDesignPro菜单）
    /// </summary>
    /// <returns></returns>
    public async Task<List<UserInfoMenuModel>> GetUserMenusAsync()
    {
        // 通过构建一个 SysUser 对象，来获取结果
        SysUser? user = BuildCurrentUser();
        if (user == null)
        {
            // 如果是在权限过滤器中抛出，将不会被处理为返回结果，因为 AuthorizationFilter 先于 ActionFilter
            //throw AppResultException.Status401Unauthorized("用户不存在");

            // 直接返回空结果，表示没有任何权限
            return new List<UserInfoMenuModel>();
        }

        // 获取结果
        return await GetUserMenusAsync(user);
    }

    /// <summary>
    /// 获取用户菜单列表（AntDesignPro菜单）
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<UserInfoMenuModel>> GetUserMenusAsync(Guid userId)
    {
        // 关联 UserRole 查询用户
        var user = await _context.Set<SysUser>()
            .Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
            .Where(u => u.Id == userId)
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw AppResultException.Status404NotFound("用户不存在");
        }

        return await GetUserMenusAsync(user);
    }

    /// <summary>
    /// 获取用户菜单列表（AntDesignPro菜单）
    /// </summary>
    /// <param name="user">包含角色信息的用户数据</param>
    /// <returns></returns>
    public async Task<List<UserInfoMenuModel>> GetUserMenusAsync(SysUser user)
    {
        if (user.AdminType == AdminType.SuperAdmin)
        {
            // 超级管理员用户
            // 优先读缓存
            List<MenuCacheItem> menuCacheItems = await _cacheService.GetUserMenusAsync(user.Id);
            if (menuCacheItems.Count > 0)
            {
                return MapperHelper.Map<List<UserInfoMenuModel>>(menuCacheItems.Distinct());
            }

            // 从数据库读取菜单列表
            var menus = await _context.Set<SysMenu>()
                .Where(m => m.IsEnabled)
                .Where(m => m.Type != MenuType.Button)
                .OrderBy(m => m.Sort).ThenBy(m => m.Id)
                .ToListAsync();

            // 缓存
            menuCacheItems = MapperHelper.Map<List<MenuCacheItem>>(menus);
            await _cacheService.SetUserMenuAsync(user.Id, menuCacheItems);

            // 返回结果
            return MapperHelper.Map<List<UserInfoMenuModel>>(menus);
        }
        else
        {
            // 其他用户
            // 获取用户角色列表
            var roleIds = user.UserRoles.Select(ur => ur.RoleId);

            // 返回角色菜单列表
            return await GetRoleMenusAsync(roleIds.ToArray());
        }
    }

    /// <summary>
    /// 获取角色菜单列表（AntDesignPro菜单）
    /// </summary>
    /// <param name="roleIds"></param>
    /// <returns></returns>
    public async Task<List<UserInfoMenuModel>> GetRoleMenusAsync(params Guid[] roleIds)
    {
        // 优先读取缓存
        List<MenuCacheItem> menuCacheItems = await _cacheService.GetRoleMenusAsync(roleIds);
        if (menuCacheItems.Count > 0)
        {
            return MapperHelper.Map<List<UserInfoMenuModel>>(menuCacheItems.Distinct());
        }

        // 没有缓存，读数据库
        List<SysMenu> menus = new List<SysMenu>();
        var roles = await _context.Set<SysRole>()
            .Include(r => r.RoleMenus.Where(rm => rm.Menu!.IsEnabled)
                                     .Where(rm => rm.Menu!.Type != MenuType.Button)
            )
            .ThenInclude(rm => rm.Menu)
            .Where(r => roleIds.Contains(r.Id))
            .ToListAsync();

        foreach (var role in roles)
        {
            List<SysMenu> roleMenus = role.RoleMenus
                .Where(rm => rm.Menu != null)
                .Select(rm => rm.Menu!)
                .ToList();

            if (roleMenus.Count > 0)
            {
                // 添加到列表
                menus.AddRange(roleMenus);

                // 添加缓存
                var roleMenuCacheItems = MapperHelper.Map<List<MenuCacheItem>>(roleMenus);
                await _cacheService.SetRoleMenuAsync(role.Id, roleMenuCacheItems);
            }
        }

        return MapperHelper.Map<List<UserInfoMenuModel>>(menus);
    }

    /// <summary>
    /// 获取所有权限
    /// </summary>
    /// <returns></returns>
    public async Task<List<string>> GetAllPermissionsAsync()
    {
        return await GetUserPermissionsAsync(new SysUser() { Id = Guid.Empty });
    }

    /// <summary>
    /// 获取当前用户权限列表（钮权限标识）
    /// </summary>
    /// <returns></returns>
    public async Task<List<string>> GetUserPermissionsAsync()
    {
        // 通过构建一个 SysUser 对象，来获取结果

        SysUser? user = BuildCurrentUser();
        if (user == null)
        {
            // 如果是在权限过滤器中抛出，将不会被处理为返回结果，因为 AuthorizationFilter 先于 ActionFilter
            //throw AppResultException.Status401Unauthorized("用户不存在");

            // 直接返回空结果，表示没有任何权限
            return new List<string>();
        }

        // 获取结果
        return await GetUserPermissionsAsync(user);
    }

    /// <summary>
    /// 获取用户权限列表（钮权限标识）
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<string>> GetUserPermissionsAsync(Guid userId)
    {
        // 关联 UserRole 查询用户
        var user = await _context.Set<SysUser>()
            .Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
            .Where(u => u.Id == userId)
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw AppResultException.Status404NotFound("用户不存在");
        }

        return await GetUserPermissionsAsync(user);
    }

    /// <summary>
    /// 获取用户权限列表（钮权限标识）
    /// </summary>
    /// <param name="user">包含角色信息的用户数据</param>
    /// <returns></returns>
    private async Task<List<string>> GetUserPermissionsAsync(SysUser user)
    {
        if (user.AdminType == AdminType.SuperAdmin || user.Id == Guid.Empty)
        {
            /*   List<string> result = await _cacheService.GetUserPermissionsAsync(user.Id);
               if (result.Count > 0)
               {
                   return result.Distinct().ToList();
               }*/

            List<string> permissions = await _context.Set<SysMenu>()
                .Where(m => m.IsEnabled)
                .Where(m => m.Type == MenuType.Button)
                .Where(m => !string.IsNullOrEmpty(m.Permission))
                .Select(m => m.Permission!)
                .Distinct()
                .ToListAsync();

            //await _cacheService.SetUserPermissionAsync(user.Id, permissions);

            return permissions;
        }
        else
        {
            var roleIds = user.UserRoles.Select(ur => ur.RoleId);

            return await GetRolePermissionsAsync(roleIds.ToArray());
        }
    }

    /// <summary>
    /// 获取角色权限列表（钮权限标识）
    /// </summary>
    /// <param name="roleIds"></param>
    /// <returns></returns>
    public async Task<List<string>> GetRolePermissionsAsync(params Guid[] roleIds)
    {
        // 优先从缓存获取
        /*       List<string> result = await _cacheService.GetRolePermissionsAsync(roleIds);
               if (result.Count > 0)
               {
                   return result.Distinct().ToList();
               }*/
        List<string> result = new List<string>();

        // 从数据库读取
        var roles = await _context.Set<SysRole>()
      .Include(r => r.RoleMenus.Where(rm => rm.Menu!.IsEnabled)
                               .Where(rm => rm.Menu!.Type == MenuType.Button)
      )
      .ThenInclude(rm => rm.Menu)
      .Where(r => roleIds.Contains(r.Id))
      .ToListAsync();

        foreach (var role in roles)
        {
            var permissions = role.RoleMenus
                .Where(rm => rm.Menu != null)
                .Select(rm => rm.Menu!)
                .Where(m => !string.IsNullOrEmpty(m.Permission))
                .Select(m => m.Permission!)
                .Distinct()
                .ToList();

            if (permissions.Count > 0)
            {
                // 添加到结果列表
                result.AddRange(permissions);

                // 添加缓存
                await _cacheService.SetRolePermissionAsync(role.Id, permissions);
            }
        }

        return result;
    }

    private SysUser? BuildCurrentUser()
    {
        if (!_currentUser.UserId.HasValue)
        {
            return default;
        }

        // 用户角色信息
        List<SysUserRole> userRoles = new List<SysUserRole>();
        foreach (var roleId in _currentUser.Roles)
        {
            var userRole = new SysUserRole()
            {
                UserId = _currentUser.UserId.Value,
                RoleId = new Guid(roleId),
            };
            userRoles.Add(userRole);
        }

        // 构建一个 SysUser 对象
        SysUser user = new SysUser()
        {
            Id = _currentUser.UserId.Value,
            UserRoles = userRoles
        };

        return user;
    }

    public async Task LogOut(string account)
    {
        await PublishLoginLog(_currentUser.UserName ?? account, 0, 1, null);
    }

    private async Task PublishLoginLog(string account, int loginSource, int loginType, string? error)
    {
        if (!string.IsNullOrEmpty(account))
        {
            var httpRequest = _httpContextAccessor?.HttpContext?.Request;
            var clientInfo = httpRequest.Headers.ContainsKey("User-Agent") ? Parser.GetDefault().Parse(httpRequest.Headers["User-Agent"]) : null;
            var @event = new LoginEvent()
            {
                LoginSource = loginSource,
                LoginType = loginType,
                Account = account,
                IsSuccess = string.IsNullOrWhiteSpace(error) ? true : false,
                Browser = clientInfo?.UA.Family + clientInfo?.UA.Major,
                OperatingSystem = clientInfo?.OS.Family + clientInfo?.OS.Major,
                Ip = _httpContextAccessor?.HttpContext?.GetRequestIPv4(),
                Result = error,
                ElapsedTime = null,
                OperatingTime = DateTime.Now,
            };
            await _publisher.PublishAsync(@event);
        }
    }

    public async Task<AppLoginOutPutModel> AppLogin(AppLoginModel login)
    {
        var result = new AppLoginOutPutModel();
        var error = string.Empty;
        SysUser loginUser = null;
        Guid? loginOrgId = null;
        int? relationship = null;
        string? classesId = null;
        string? childId = null;
        string? currentUserImageId = null;
        if (login.ConfirmData != null)
        {
            result.UserInfo = new LoginUserModel();
            if (login.LoginType == LoginType.ParentSide.GetHashCode())
            {
                var preSchool = JsonConvert.DeserializeObject<PreSchoolModel>(login.ConfirmData.ToString());
                loginUser = new SysUser();
                loginUser.UserName = login.Phone;
                loginUser.OrganizationId = preSchool.OrgId;
                loginUser.Phone = login.Phone;
                loginUser.AdminType = AdminType.None;
                loginUser.Id = preSchool.ParentId.Value;
                loginUser.Name = preSchool.ParentName;
                loginOrgId = preSchool.OrgId;

                relationship = preSchool.Relationship;
                classesId = preSchool.ClassesId?.ToString();
                childId = preSchool.ChildId?.ToString();
                result.UserInfo.OrgId = preSchool.OrgId;
                result.UserInfo.OrgName = preSchool.OrgName;
                result.UserInfo.Avatar = preSchool.Avatar;
                result.UserInfo.ChildId = preSchool.ChildId;
                result.UserInfo.ChildName = preSchool.ChildName;
                result.UserInfo.ClassesId = preSchool.ClassesId;
                result.UserInfo.ClassesName = preSchool.ClassesName;
                result.UserInfo.Relationship = preSchool.Relationship;
            }
            else
            {
                var orgModel = JsonConvert.DeserializeObject<OrgConfirmModel>(login.ConfirmData.ToString());
                var user = await _context.Set<SysUser>()
                .Include(u => u.UserRoles)
                 .Include(u => u.Organization)
                 .Include(u => u.Position)
                .Where(u => u.Phone == login.Phone)
                .Where(u => u.Password == login.Password)
                .FirstOrDefaultAsync();

                loginUser = user;
                loginOrgId = orgModel.OrgId;
                result.UserInfo.OrgId = user.OrganizationId;
                result.UserInfo.OrgName = user.Organization?.Name;
                result.UserInfo.PostId = user.PositionId;
                result.UserInfo.PostName = user.Position?.Name;
                result.UserInfo.Avatar = await _fileInfoService.GetUserPortrait(loginUser.Id);
            }
            if (loginUser.AdminType != AdminType.SuperAdmin)
            {

                var includeEmployeeAttendanceMenuCode = _simpleService.GetService<IConfiguration>()["AppSetting:IncludeEmployeeAttendanceMenuCode"];
                var userMenus = await GetUserMenusAsync(loginUser);
                if (userMenus != null && userMenus.Any())
                {
                    result.UserInfo.IncludeEmployeeAttendance = userMenus.Any(c => c.Name == includeEmployeeAttendanceMenuCode);
                }
            }
            else
            {
                result.UserInfo.IncludeEmployeeAttendance = true;
            }

            result.UserInfo.UserId = loginUser.Id;
            result.UserInfo.Account = loginUser.UserName;
            result.UserInfo.UserName = loginUser.Name;
            result.UserInfo.Sex = loginUser.Gender.GetHashCode();
            currentUserImageId = result.UserInfo.Avatar;
        }
        else
        {
            if (login.LoginType == LoginType.GardenSide.GetHashCode())
            {
                // 根据手机号获取用户信息
                var user = await _context.Set<SysUser>()
                     .Include(u => u.UserRoles)
                     .Include(u => u.Organization)
                     .Include(u => u.Position)
                     .Where(u => u.Phone == login.Phone)
                     .Where(u => u.Password == login.Password)
                     .FirstOrDefaultAsync();

                if (user == null)
                {
                    error = "手机号不存在或密码不匹配";
                }
                else if (!user.IsEnabled)
                {
                    error = "该账号已被停用";
                }
                else
                {
                    // 查看当前用户有多少组织机构权限（只看一级机构）
                    var orgs = await _organizationService.GetPrimaryOrganization(user.AdminType == AdminType.SuperAdmin, user.Id);
                    if (orgs.Count > 1)
                    {
                        result.IsMultiple = true;
                        result.ConfirmList = orgs.Select(s => new OrgConfirmModel
                        {
                            OrgId = s.Id,
                            OrgName = s.Name,
                            UserId = user.Id,
                        }).ToList();
                    }
                    else
                    {
                        loginUser = user;
                        loginOrgId = orgs.FirstOrDefault().Id;
                        result.UserInfo = new LoginUserModel();
                        result.UserInfo.UserId = loginUser.Id;
                        result.UserInfo.Account = loginUser.UserName;
                        result.UserInfo.UserName = loginUser.Name;
                        result.UserInfo.Sex = loginUser.Gender.GetHashCode();
                        result.UserInfo.OrgId = loginOrgId;
                        result.UserInfo.OrgName = loginUser.Organization?.Name;
                        result.UserInfo.PostId = loginUser.PositionId;
                        result.UserInfo.PostName = loginUser.Position?.Name;
                        result.UserInfo.Avatar = await _fileInfoService.GetUserPortrait(loginUser.Id);
                    }
                }
            }
            else
            {
                // 根据手机号查看家长信息
                var parents = await _context.Set<ChildrenParent>()
                   .Include(u => u.Parent)
                   .Include(u => u.Child)
                   .Where(u => u.Parent != null && u.Parent.PhoneNumber == login.Phone && u.Child.ChildState == EnumChildState.Reading)
                   .ToListAsync();
                if (!parents.Any())
                {
                    error = "当前手机号未绑定在系统中，请联系幼儿负责人绑定手机号";
                }
                else
                {
                    if (parents.Exists(s => !s.Parent.IsOpenWechat))
                    {
                        error = "当前手机号未开通微信端，请联系幼儿负责人开通";
                    }
                    if (!parents.Exists(s => s.Parent.PassWordMD5 == login.Password))
                    {
                        error = "密码错误，请输入正确的密码";
                    }

                    if (parents.Count > 1)
                    {
                        result.IsMultiple = true;
                        var orgs = await _context.Set<SysOrganization>().ToListAsync();
                        var classes = await _context.Set<SysClasses>().ToListAsync();
                        result.ConfirmList = parents.Select(s => new PreSchoolModel
                        {
                            OrgId = s.Child.OrganizationId,
                            OrgName = orgs.FirstOrDefault(o => o.Id == s.Child.OrganizationId)?.Name,
                            ChildName = s.Child.Name,
                            ChildId = s.Child.Id,
                            ParentId = s.Parent.Id,
                            ParentName = s.Parent.Name,
                            Relationship = s.Relationship.GetHashCode(),
                            ClassesId = s.Child.ClassesId,
                            ClassesName = classes.FirstOrDefault(o => o.Id.ToString() == s.Child.ClassesId)?.Name,
                            Avatar = s.Parent.ImgId?.ToString(),
                        }).ToList();
                    }
                    else
                    {
                        var parent = parents.FirstOrDefault();
                        loginUser = new SysUser
                        {
                            AdminType = AdminType.None,
                            OrganizationId = parent.Parent.OrganizationId,
                            Phone = parent.Parent.PhoneNumber,
                            UserName = parent.Parent.PhoneNumber,
                            Id = parent.Parent.Id,
                            Name = parent.Parent?.Name,
                            Gender = parent.Parent.GenderType,
                        };
                        loginOrgId = parent.Parent.OrganizationId;
                        relationship = parent.Relationship.GetHashCode();
                        classesId = parent.Child?.ClassesId;
                        childId = parent.ChildId.ToString();

                        result.UserInfo = new LoginUserModel();
                        result.UserInfo.UserId = loginUser.Id;
                        result.UserInfo.Account = loginUser.UserName;
                        result.UserInfo.UserName = loginUser.Name;
                        result.UserInfo.Sex = parent.Parent.GenderType.GetHashCode();
                        result.UserInfo.OrgId = parent.Parent.OrganizationId;
                        result.UserInfo.Avatar = null; //TODO 返回头像id
                        result.UserInfo.ChildId = parent.ChildId;
                        result.UserInfo.ChildName = parent.Child?.Name;
                        result.UserInfo.ChildAvatar = parent.Child?.ImgId.ToString();
                        result.UserInfo.ClassesId = parent.Child?.ClassesId;
                        result.UserInfo.Relationship = parent.Relationship.GetHashCode();
                        result.UserInfo.Avatar = parent.Parent.ImgId?.ToString();
                        if (result.UserInfo.OrgId.HasValue)
                        {
                            result.UserInfo.OrgName = _context.Set<SysOrganization>().Where(s => s.Id == result.UserInfo.OrgId).FirstOrDefault()?.Name;
                        }
                        if (!string.IsNullOrWhiteSpace(result.UserInfo.ClassesId))
                        {
                            result.UserInfo.ClassesName = _context.Set<SysClasses>().Where(s => s.Id.ToString() == result.UserInfo.ClassesId).FirstOrDefault()?.Name;
                        }
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(error))
            {
                #region 登录日志
                PublishLoginLog(loginUser?.Name ?? login.Phone, 1, 0, error);
                #endregion
                throw AppResultException.Status403Forbidden(error);
            }
            if (result.IsMultiple)
            {
                return result;
            }
        }
        #region 登录日志
        PublishLoginLog(loginUser.Name, 1, 0, null);
        #endregion

        // 用户信息
        List<Claim> claims = new List<Claim>()
        {
            new Claim(SimpleClaimTypes.UserId, loginUser.Id.ToString()),
            new Claim(SimpleClaimTypes.Name, loginUser.Name ?? ""),
            new Claim(SimpleClaimTypes.Email, loginUser.Email?? ""),
            new Claim(SimpleClaimTypes.AdminType, loginUser.AdminType.ToString()),
            new Claim(SimpleClaimTypes.OrganizationId, loginUser.OrganizationId.ToString()),
            new Claim(SimpleClaimTypes.LoginSource, "1"),
            new Claim(SimpleClaimTypes.LoginType, login.LoginType.ToString()),
            new Claim(SimpleClaimTypes.LoginOrganizationId, loginOrgId.ToString()),
            new Claim(SimpleClaimTypes.CurrentUserImageId, currentUserImageId ?? string.Empty )
        };

        if (login.LoginType == LoginType.ParentSide.GetHashCode())
        {
            claims.Add(new Claim(SimpleClaimTypes.Relationship, relationship?.ToString()));
            claims.Add(new Claim(SimpleClaimTypes.ClassesId, classesId));
            claims.Add(new Claim(SimpleClaimTypes.ChildId, childId));
        }

        string[] roles = loginUser.UserRoles.Select(ur => ur.RoleId.ToString()).ToArray();

        // 生成 token
        var jwtTokenModel = new JwtTokenModel(loginUser.UserName, claims, roles);
        jwtTokenModel.Expiration = 2592000;// app登录默认30天
        result.Token = JwtHelper.Create(jwtTokenModel);

        result.UserInfo.IncludeEmployeeAttendance = result.UserInfo.PostName == "园长" ? true : false;

        return result;
    }

    public async Task<string> GetWeChatInfo(string code)
    {
        var appid = _simpleService.GetService<IConfiguration>()["WeChat:AppId"];
        var appSecret = _simpleService.GetService<IConfiguration>()["WeChat:AppSecret"];

        string serviceAddress = $"https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={appSecret}&js_code={code}&grant_type=authorization_code";
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(serviceAddress);
            var response = await client.GetAsync(serviceAddress);
            var result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }

    public async Task<string> WechatMsgSecCheck(WechatMsgSecCheckInput input)
    {
        var token = await WechatGetToken();
        string jsonContent = JsonConvert.SerializeObject(input);
        string serviceAddress = $"https://api.weixin.qq.com/wxa/msg_sec_check?access_token={token}";
        using (HttpClient client = new HttpClient())
        {
            var conter = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            client.DefaultRequestHeaders.Add("Method", "Post");
            var response = await client.PostAsync(serviceAddress, conter);
            var result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }

    public async Task<string> WechatMediaCheck(WechatMediaCheckInput input)
    {
        var token = await WechatGetToken();
        string jsonContent = JsonConvert.SerializeObject(input);
        string serviceAddress = $"https://api.weixin.qq.com/wxa/media_check_async?access_token={token}";
        using (HttpClient client = new HttpClient())
        {
            var conter = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            client.DefaultRequestHeaders.Add("Method", "Post");
            var response = await client.PostAsync(serviceAddress, conter);
            var result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }

    public async Task<string> WechatGetToken()
    {
        var token = await _cacheService.GetWechatTokenAsync();
        if (token == null || token.ExpireDate < DateTime.Now)
        {
            await _cacheService.ClearWechatTokenAsync();
            var appid = _simpleService.GetService<IConfiguration>()["WeChat:AppId"];
            var appSecret = _simpleService.GetService<IConfiguration>()["WeChat:AppSecret"];
            string serviceAddress = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&secret={appSecret}&appid={appid}";
            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(serviceAddress);
                var response = await client.GetAsync(serviceAddress);
                var json = JsonConvert.DeserializeObject<WechatGetTokenResult>(await response.Content.ReadAsStringAsync());
                await _cacheService.SetWechatTokenAsync(new WechatToken
                {
                    Token = json.Access_token,
                    ExpireDate = DateTime.Now.AddHours(1.5),
                });
                return json.Access_token;
            }
        }
        else
        {
            return token.Token;
        }
    }




}
